package com.jxmcloud.business.cut.service.impl.user;

import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.jxmcloud.business.cut.constants.CutConstants;
import com.jxmcloud.business.cut.constants.CutSaveKey;
import com.jxmcloud.business.cut.dtoCommon.BagInfoDto;
import com.jxmcloud.business.cut.dtoCommon.EServerNoticeTypeDto;
import com.jxmcloud.business.cut.enums.ProgressTypeEnum;
import com.jxmcloud.business.cut.json.DataConfigGlobalGlobalLoader;
import com.jxmcloud.business.cut.json.DataConfigInviteAwardLoader;
import com.jxmcloud.business.cut.json.DataConfigInviteProgressLoader;
import com.jxmcloud.business.cut.json.DataConfigService;
import com.jxmcloud.business.cut.model.database.DBUserActivityInfo;
import com.jxmcloud.business.cut.model.database.DBUserFlowInfo;
import com.jxmcloud.business.cut.model.database.DBUserInviteSuccess;
import com.jxmcloud.business.cut.service.database.IUserActivityInfoDBService;
import com.jxmcloud.business.cut.service.database.IUserFlowDBService;
import com.jxmcloud.business.cut.service.database.IUserInviteSuccessDBService;
import com.jxmcloud.business.cut.service.database.IUserLoginInfoDBService;
import com.jxmcloud.business.cut.service.logic.IConfigActionUtil;
import com.jxmcloud.business.cut.service.user.*;
import com.jxmcloud.business.cut.util.MyTool;
import com.jxmcloud.business.cut.vo.ActivityVo;
import com.jxmcloud.business.cut.vo.client.GetInviteAwardProgressVo;
import com.jxmcloud.business.cut.vo.client.GetInviteAwardVo;
import com.jxmcloud.business.cut.vo.json.*;
import com.jxmcloud.business.cut.vo.user.PlayerInfoVo;
import com.jxmcloud.business.cut.vo.user.UserActivityVo;
import com.jxmcloud.business.cut.vo.user.UserCashDetailItemVo;
import com.xlcloud.platform.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * 用户活动模块实现
 */
@Service
@Slf4j
public class UserActivityServiceImpl implements IUserActivityService {
    @Autowired
    private IUserActivityInfoDBService userActivityDBService;
    @Resource
    private IUserFlowService userFlowService;
    @Resource
    private IUserInviteSuccessDBService inviteSuccessDBService;
    @Resource
    private IUserLoginInfoDBService userLoginInfoDBService;
    @Resource
    private DataConfigInviteAwardLoader dataConfigInviteAwardLoader;
    @Resource
    private IUserCashDetailListService userCashDetailListService;
    @Resource
    private IConfigActionUtil configActionUtil;
    @Resource
    private IUserManagerService userManagerService;
    @Resource
    private DataConfigService dataConfigService;
    @Resource
    private DataConfigGlobalGlobalLoader dataConfigGlobalGlobalLoader;
    @Resource
    private IUserBagService userBagService;
    @Resource
    @Lazy  // 添加延迟加载注解
    private IUserOrderService userOrderService;
    @Resource
    private IUserFlowDBService userFlowDBService;
    @Resource
    private DataConfigInviteProgressLoader dataConfigInviteProgressLoader;
    @Resource
    private IUserActivityService userActivityService;
    @Resource
    private IUserInviteSuccessDBService userInviteSuccessDBService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveToDb(PlayerInfoVo player, String key) {
        if (key.equals(CutSaveKey.USER_ACTIVITY_NOTICE_TYPE_LIST)) {
            Integer uid = player.getBase().getUid();
            Integer activityId = player.getActivity().getActivityId();
            Integer[] noticeTypeList = player.getActivity().getNoticeTypeList();

            userActivityDBService.updateNoticeList(uid, activityId, noticeTypeList);
        } else if (key.equals(CutSaveKey.USER_ACTIVITY_NEWS_COUNT)) {
            Integer uid = player.getBase().getUid();
            Integer activityId = player.getActivity().getActivityId();
            Integer newsCount = player.getActivity().getNewUserCount();
            userActivityDBService.updateNewsCount(uid, activityId, newsCount);
        } else if (key.equals(CutSaveKey.USER_ACTIVITY_SHARE_SUCCESS)) {
            Integer uid = player.getBase().getUid();
            Integer activityId = player.getActivity().getActivityId();
            Integer shareCount = player.getActivity().getShareCount();
            userActivityDBService.updateShareCount(uid, activityId, shareCount);
        } else if (key.equals(CutSaveKey.USER_ACTIVITY_BEGAN_TIME)) {
            Integer uid = player.getBase().getUid();
            Integer activityId = player.getActivity().getActivityId();
            Integer beganTime = player.getActivity().getBeganTime();
            userActivityDBService.updateBeganTime(uid, activityId, beganTime);
        }

        return true;
    }

    @Override
    public boolean loadFromDb(PlayerInfoVo player, Integer uid) {
        DBUserActivityInfo dbUserActivityInfo = userActivityDBService.selectByUidAndActivityIdOnDoing(uid);
        if (!Objects.isNull(dbUserActivityInfo)) {
            UserActivityVo activity = player.getActivity();
            BeanUtils.copyProperties(dbUserActivityInfo, activity);
            activity.setStartId(dbUserActivityInfo.getActivityStartId());
            activity.setNoticeTypeList(dbUserActivityInfo.getNotice());

            Date beganTimeDate = dbUserActivityInfo.getBeganTime();
            Long beganTimeL = DateUtil.dateToTime(beganTimeDate);
            activity.setBeganTime(beganTimeL.intValue());

            Date createTimeDate = dbUserActivityInfo.getCreateTime();
            Long createTimeL = DateUtil.dateToTime(createTimeDate);
            activity.setCreateTime(createTimeL.intValue());

            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(PlayerInfoVo player, Integer uid) {
        this.makeNewActivity(player);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void makeNewActivity(PlayerInfoVo player) {
        ActivityVo activityVo = configActionUtil.getRandomActivity(player.getBase().getUid(), DateUtil.getDate());
        if (ObjectUtil.isNull(activityVo)) {
            log.error("未获取到随机活动");
            return;
        }
        UserActivityVo activity = player.getActivity();
        activity.setActivityId(activityVo.getId());
        activity.setStartId(activityVo.getStartId());
        Long nowTimeLong = MyTool.getCurrentTime();
        activity.setBeganTime(nowTimeLong.intValue());
        userFlowService.refreshFlowData(player);

        // 插入一条新的活动数据
        DBUserActivityInfo dbData = DBUserActivityInfo.builder().build();
        dbData.setUid(player.getBase().getUid());
        dbData.setActivityId(activity.getActivityId());
        dbData.setActivityStartId(activity.getStartId());
        dbData.setWatchLive(0);
        dbData.setGainPrize(0);
        dbData.setStatus(0);
        dbData.setNotice(new Integer[0]);
        dbData.setImageUrl(null);
        dbData.setNewUserCount(0);
        dbData.setCreateTime(new Date());
        dbData.setShareCount(0);
        dbData.setBeganTime(new Date());

        userActivityDBService.insertIntoData(dbData);
    }

    /**
     * 检测活动是否失效  24小时
     *
     * @param player
     * @return
     */
    @Override
    public boolean checkNewActivityValid(PlayerInfoVo player) {
        Integer activityId = player.getActivity().getActivityId();
        if (activityId.equals(0)) {
            this.makeNewActivity(player);
            return true;
        }
        // 验证活动时间
        this.checkReliveActivity(player);
        return true;
    }

    /**
     * 检测复活
     * @param player
     * @return 复活步骤
     */
    public Integer checkReliveActivity(PlayerInfoVo player) {
        Integer activityId = player.getActivity().getActivityId();

        // 活动是否已结束
        boolean isActEnd = this.isActivityEnd(activityId);

        // 能否复活
        Boolean isRelive = this.isNeedRelive(player);

        // 新开用户活动
        if (isActEnd) {
            this.startNewActivity(player);
        } else if (isRelive) {
            // 有效时间结束.
            // 当前钱币若为0, 则重置活动
            ConfigGlobalGlobalVo globalConfig = dataConfigGlobalGlobalLoader.getConfigGlobalGlobal();
            if (ObjectUtil.isNull(globalConfig)) {
                return 0;
            }
            Integer moneyId = globalConfig.getItemIdCash();
            Integer moneyCount = userBagService.getItemCount(player, moneyId);
            if (moneyCount <= 0) {
                // 重置
                this.resetActivity(player);
            } else {
                // 复活
                this.reliveUserActivity(player);
            }
        }

        return player.getFlowInfo().getStepId();
    }

    /**
     * 是否需要复活
     * @param player
     * @return
     */
    @Override
    public boolean isNeedRelive(PlayerInfoVo player) {
        Integer activityId = player.getActivity().getActivityId();

        // 系统活动时间
        ConfigActivityStartVo activityConfig = dataConfigService.getConfigActivityStartConfig(activityId);
        if (ObjectUtil.isNull(activityConfig)) {
            log.error("未获取到开局活动配置: {}", activityId);
            return false;
        }
        // 是否允许
        Boolean canRelive = MyTool.isTure(activityConfig.getCanRelive());
        if (!canRelive) {
            return false;
        }

        // 用户的有效时长, s
        ConfigGlobalGlobalVo globalConfig = dataConfigGlobalGlobalLoader.getConfigGlobalGlobal();
        if (ObjectUtil.isNull(globalConfig)) {
            log.error("未获取到全局配置: getConfigGlobalGlobal()");
            return false;
        }
        // 有效时间配置
        Integer userActValidTime = globalConfig.getUserActValidTime();
        if (ObjectUtil.isNull(userActValidTime)) {
            return false;
        }

        // 用户起始有效时间戳s
        Integer userActBeganTime = player.getActivity().getBeganTime();
        if (!MyTool.isTure(userActBeganTime)) {
            return false;
        }

        // 有效结束时间戳
        Integer userActEndTime = userActBeganTime + userActValidTime;

        // 当前时间戳s
        Integer nowTimeInt = MyTool.getCurrentTime().intValue();

        // 判断活动是否结束
        boolean isActEnd = false;
        // 活动结束时间s
        Integer endTime = this.getActivityEndTime(activityId);
        if (MyTool.isTure(endTime)) {
            isActEnd = nowTimeInt >= endTime;
        }
        if (isActEnd) {
            return false;
        }

        // 有效是否结束
        boolean isValidEnd = nowTimeInt >= userActEndTime;
        if (isValidEnd) {
            return true;
        }

        return false;
    }

    /**
     * 活动是否已结束
     *
     * @param activityId
     * @return
     */
    @Override
    public boolean isActivityEnd(Integer activityId) {
        Integer endTime = this.getActivityEndTime(activityId);
        if (ObjectUtil.isNull(endTime)) {
            return false;
        }

        // 当前时间戳s
        Integer nowTimeInt = MyTool.getCurrentTime().intValue();

        // 活动结束
        boolean isActEnd = nowTimeInt >= endTime;
        if (isActEnd) {
            return true;
        }
        return false;
    }

    /**
     * 获取活动结束时间戳s
     * @param activityId
     * @return
     */
    private Integer getActivityEndTime(Integer activityId) {
        // 系统活动时间
        ConfigActivityStartVo activityConfig = dataConfigService.getConfigActivityStartConfig(activityId);
        if (ObjectUtil.isNull(activityConfig)) {
            log.error("未获取到开局活动配置: {}", activityId);
            return null;
        }

        // 无限时间
        String endTimeConfig = activityConfig.getEndTime();
        if (!MyTool.isTure(endTimeConfig)) {
            return null;
        }
        endTimeConfig = endTimeConfig.trim();

        //
        String endTimeStr = endTimeConfig + " 23:59:59";
        Integer endTime = MyTool.convertTimeStrToLong(endTimeStr).intValue();
        if (ObjectUtil.isNull(endTime)) {
            log.error("活动结束时间转换失败");
            return null;
        }
        return endTime;
    }


    /**
     * 新开用户活动
     *
     * @param player
     */
    private void startNewActivity(PlayerInfoVo player) {
        this.overUserActivity(player);
        this.makeNewActivity(player);
    }

    /**
     * 结束当前活动
     * @param player
     */
    private void overUserActivity(PlayerInfoVo player) {
        Integer uid = player.getBase().getUid();
        DBUserActivityInfo dbUserActivityInfo = userActivityDBService.selectByUidAndActivityIdOnDoing(uid);
        dbUserActivityInfo.setStatus(-1);
        userActivityDBService.updateById(dbUserActivityInfo);
    }

    /**
     * 复活用户活动
     *
     * @param player
     */
    private void reliveUserActivity(PlayerInfoVo player) {
        Integer nowTimeInt = MyTool.getCurrentTime().intValue();
        // 更新开始时间
        player.getActivity().setBeganTime(nowTimeInt);
        // 记录当前流程. 如果当前已经处于复活流程, 则不更新
        Integer curReliveStep = player.getFlowInfo().getReviveStepId();
        if (!MyTool.isTure(curReliveStep)) {
            Integer stepId = player.getFlowInfo().getStepId();
            userFlowService.updateReviveStepId(player, stepId);
        }

        // 进入复活流程
        Integer startId = player.getActivity().getStartId();
        ConfigStartVo configStart = dataConfigService.getConfigStartConfig(startId);
        if (ObjectUtil.isNull(configStart)) {
            log.error("未找到配置");
            return;
        }
        Integer reliveStep = configStart.getReliveStep();
        if (!MyTool.isTure(reliveStep)) {
            log.warn("未配置复活步骤");
            return;
        }
        userFlowService.enterNextProgress(player, reliveStep);
        log.info("进入复活流程 {}", reliveStep);

        // tag刷新到数据库
        player.getMaster().getSaveList().add(CutSaveKey.USER_ACTIVITY_BEGAN_TIME);
    }


    @Override
    public Integer checkWatchLiveFinish(PlayerInfoVo player) {
        Integer watchLive = player.getActivity().getWatchLive();
        if (watchLive.equals(1)) {
            return 1;
        }
        return 0;
    }

    /**
     * 检测新增邀请人
     *
     * @param player 助力用户
     * @param targetUid 被助力uid
     * @param targetActivityId
     * @param userTypeParam 1是新用户, 0是老用户, null则会查询判断用户类型
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean checkAddInvitedPlayer(PlayerInfoVo player, Integer targetUid, Integer targetActivityId, Integer userTypeParam) {
        if (player.getBase().getUid().equals(targetUid)) {
            log.warn("不能邀请自己");
            return false;
        }

        Integer helperXlId = player.getBase().getXlId().intValue();
        boolean isValid = this.checkInvitePlayerValid(helperXlId, targetUid, targetActivityId);
        if (!isValid) {
            return false;
        }
        return this.addInvitedPlayer(player, targetUid, targetActivityId, userTypeParam);
    }

    /**
     * 领取助力成功的奖励
     *
     * @param player
     * @return
     */
    @Override
    public GetInviteAwardVo getInviteSuccessAward(PlayerInfoVo player) {
        Integer uid = player.getBase().getUid();
        Integer activityId = player.getActivity().getActivityId();
        // 获取一个可领取的奖励
        DBUserInviteSuccess dbInfo = inviteSuccessDBService.selectCanGainAwardInfo(uid, activityId);
        if (ObjectUtil.isNull(dbInfo)) {
            log.error("未查询到助力成功的数据");
            return null;
        }
        // 奖励配置
        ConfigInviteAwardVo configVo = dataConfigInviteAwardLoader.getConfigById(activityId);
        if (Objects.isNull(configVo)) {
            log.error("未获取到奖励配置");
            return null;
        }
        // 新用户  老用户 奖励
        // 流程
        Integer[][] awardConfig = null;
        Integer userType = dbInfo.getUserType();
        if (userType.equals(CutConstants.USER_TYPE_NEW)) {
            awardConfig = configVo.getNewAwardItem();
        } else if (userType.equals(CutConstants.USER_TYPE_OLD)) {
            awardConfig = configVo.getOldAwardItem();
        }
        if (ObjectUtil.isNull(awardConfig)) {
            log.error("未获取到对应类型的奖励配置");
            return null;
        }

        List<BagInfoDto> itemAwards = new ArrayList<>();
        // 加奖励
        for (int i = 0; i < awardConfig.length; ++i) {
            Integer[] itemConfig = awardConfig[i];
            if (ObjectUtil.isNull(itemConfig) || itemConfig.length < 2) {
                continue;
            }
            Integer itemId = itemConfig[0];
            Integer itemCount = itemConfig[1];
            BagInfoDto bagInfo = new BagInfoDto();
            bagInfo.setId(itemId);
            bagInfo.setCount(itemCount);
            // 增加奖励
            boolean isOk = userBagService.addItem(player, itemId, itemCount);
            if (!isOk) {
                continue;
            }
            itemAwards.add(bagInfo);

            // 增加零钱记录
            Long timeData = DateUtil.dateToTime(DateUtil.newDate());
            UserCashDetailItemVo newCash = new UserCashDetailItemVo();
            newCash.setId(itemId);
            newCash.setCount(itemCount);
            newCash.setProgressId(player.getFlowInfo().getStepId());
            newCash.setTitle("助力奖励");
            newCash.setTime(timeData.intValue());

            userCashDetailListService.addNewCashDetail(player, newCash);
        }

        // 更新领取
        boolean isOk = inviteSuccessDBService.updateGainAward(dbInfo.getId());
        if (!isOk) {
            log.error("更新奖励领取状态失败!");
            return null;
        }

        // 检测是否还有
        userActivityService.isHasHelpNotice(player);

        // 回包
        GetInviteAwardVo awardVo = new GetInviteAwardVo();
        awardVo.setHelperAccount(dbInfo.getInvitedAccount());
        awardVo.setHelperIcon(dbInfo.getInvitedIcon());
        awardVo.setHelperName(dbInfo.getInvitedName());
        Long respTime = DateUtil.dateToTime(dbInfo.getRespTime());
        awardVo.setHelpTime(respTime.intValue());
        awardVo.setItemAwards(itemAwards);
        return awardVo;
    }

    @Override
    public GetInviteAwardProgressVo getInviteSuccessAwardProgress(PlayerInfoVo player) {
        Integer uid = player.getBase().getUid();
        Integer activityId = player.getActivity().getActivityId();
        // 获取一个可领取的奖励
        DBUserInviteSuccess dbInfo = inviteSuccessDBService.selectCanGainAwardInfo(uid, activityId);
        if (ObjectUtil.isNull(dbInfo)) {
            log.error("未查询到助力成功的数据");
            return null;
        }

        // 计算出进入的流程
        Integer stepId = this.calInviteShareEnterStepId(player);
        boolean isEnterOk = userFlowService.enterNextProgress(player, stepId);
        if (!isEnterOk) {
            log.error("进入下一步失败");
            return null;
        }

        // 更新词条助力记录已领取
        boolean isOk = inviteSuccessDBService.updateGainAward(dbInfo.getId());
        if (!isOk) {
            log.error("更新奖励领取状态失败!");
            return null;
        }

        // 检测是否还有
        userActivityService.isHasHelpNotice(player);

        // 回包
        GetInviteAwardProgressVo awardVo = new GetInviteAwardProgressVo();
        awardVo.setHelperAccount(dbInfo.getInvitedAccount());
        awardVo.setHelperIcon(dbInfo.getInvitedIcon());
        awardVo.setHelperName(dbInfo.getInvitedName());
        Long respTime = DateUtil.dateToTime(dbInfo.getRespTime());
        awardVo.setHelpTime(respTime.intValue());
        awardVo.setNextStepId(stepId);
        return awardVo;
    }

    @Override
    public boolean isHasHelpNotice(PlayerInfoVo player) {
        // 获取一个可领取的奖励
        Integer activityId = player.getActivity().getActivityId();
        DBUserInviteSuccess dbInfo = inviteSuccessDBService.selectCanGainAwardInfo(player.getBase().getUid(), activityId);
        if (ObjectUtil.isNull(dbInfo)) {
            return false;
        }
        if (ObjectUtil.isNull(dbInfo.getUserType())) {
            log.error("未获取到用户类型");
            return false;
        }

        boolean isNewer = dbInfo.getUserType().equals(CutConstants.USER_TYPE_NEW);

        // 加入通知
        Integer noticeType = this.getInviteNoticeType(player.getActivity().getStartId(), player.getFlowInfo().getStepId(), isNewer);
        this.addNoticeType(player, noticeType);
        return true;
    }

    /**
     * 计算进入下一步的步骤
     * @param player
     * @return
     */
    private Integer calInviteShareEnterStepId(PlayerInfoVo player) {
        Map<Integer, ConfigInviteProgressVo> configMap = dataConfigInviteProgressLoader.getConfigInviteProgressMap();
        if (ObjectUtil.isNull(configMap)) {
            log.error("未获取到分享邀请进度配置");
            return 0;
        }
        Integer activityId = player.getActivity().getActivityId();
        Integer startId = player.getActivity().getStartId();
        for (Map.Entry<Integer, ConfigInviteProgressVo> entry : configMap.entrySet()) {
            ConfigInviteProgressVo config = entry.getValue();
            if (!config.getActivityId().equals(activityId)) {
                continue;
            }
            if (!config.getStartId().equals(startId)) {
                continue;
            }
            Integer itemId = config.getItemId();
            Integer[] shareCounts = config.getShareCount();
            if (shareCounts.length < 2) {
                log.error("分享范围次数配置错误: {}", shareCounts);
                continue;
            }

            Integer curCount = userBagService.getItemCount(player, itemId);
            if (curCount >= shareCounts[0] && curCount <= shareCounts[1]) {
                return config.getShareProgressId();
            }
        }
        return 0;
    }

    /**
     * 检测邀请人有效性
     *
     * @param helperXlId 助力人
     * @param targetUid
     * @param targetActivityId
     * @return
     */
    private boolean checkInvitePlayerValid(Integer helperXlId, Integer targetUid, Integer targetActivityId) {
        // 是否已助力过
        DBUserInviteSuccess dbData = inviteSuccessDBService.selectHelpInfo(targetUid, helperXlId, targetActivityId);
        if (Objects.isNull(dbData)) {
            return true;
        }
        return false;
    }

    /**
     * 加入邀请人
     *
     * @param player
     * @param uid
     * @param activityId
     * @param userTypeParam 用户类型为 null, 则会查询判断用户类型
     */
    private boolean addInvitedPlayer(PlayerInfoVo player, Integer uid, Integer activityId, Integer userTypeParam) {
        // 判断 新老用户
        Integer userType = userTypeParam;
        if (ObjectUtil.isNull(userType)) {
            userType = this.ifNewUser(player);
        }
        if (userType.equals(CutConstants.USER_TYPE_PHONE_LACK)) {
            log.warn("电话缺失!");
            return false;
        }

        // 插入记录表
        DBUserInviteSuccess info = DBUserInviteSuccess.builder().build();
        info.setActivityId(activityId);
        info.setUid(uid);
        info.setInvitedXlId(player.getBase().getXlId());
        info.setUserType(userType);
        info.setInvitedAccount(player.getBase().getAccount());
        info.setInvitedName(player.getBase().getNickName());
        info.setInvitedIcon(player.getBase().getIcon());
        info.setInvitedMobile(player.getBase().getPhone());
        info.setRespTime(new Date());
        info.setIsGainAward(0);
        boolean isOK = inviteSuccessDBService.insertIntoData(info);
        if (!isOK) {
            log.error("插入邀请成功数据失败!");
            return false;
        }

        boolean isNewUser = userType.equals(CutConstants.USER_TYPE_NEW);

        // 更新对方的数据
        PlayerInfoVo targetPlayer = userManagerService.getUserInfoByUid(uid);
        if (ObjectUtil.isNotNull(targetPlayer)) {
            this.addNewsCount(targetPlayer);
            // 加入通知
            Integer noticeType = this.getInviteNoticeType(targetPlayer.getActivity().getStartId(), targetPlayer.getFlowInfo().getStepId(), isNewUser);
            this.addNoticeType(targetPlayer, noticeType);
            // 刷新缓存信息
            userManagerService.refreshPlayerCache(targetPlayer);
        } else {
            DBUserActivityInfo dbActivityInfo = userActivityDBService.selectOne(uid, activityId, 0);
            if (ObjectUtil.isNotNull(dbActivityInfo)) {
                // 更新邀请数
                Integer newsCount = dbActivityInfo.getNewUserCount() + 1;
                userActivityDBService.updateNewsCount(uid, activityId, newsCount);

                // 流程
                DBUserFlowInfo dbFlow = userFlowDBService.selectOne(uid, activityId);
                if (ObjectUtil.isNotNull(dbFlow)) {
                    // 更新通知
                    Integer noticeType = this.getInviteNoticeType(dbActivityInfo.getActivityStartId(), dbFlow.getStepId(), isNewUser);
                    if (MyTool.isTure(noticeType)) {
                        Integer[] noticeList = new Integer[0];
                        if (ObjectUtil.isNotNull(dbActivityInfo.getNotice())) {
                            noticeList = dbActivityInfo.getNotice();
                        }
                        ArrayList<Integer> array = Lists.newArrayList(noticeList);
                        if (!array.contains(noticeType)) {
                            array.add(noticeType);
                            noticeList = array.toArray(new Integer[0]);
                            userActivityDBService.updateNoticeList(uid, activityId, noticeList);
                        }
                    }
                }
            }
        }
        return true;
    }

    /**
     * 获取邀请通知类型
     * @param curStartId
     * @return
     */
    private Integer getInviteNoticeType(Integer curStartId, Integer curStepId, boolean isNewUser) {
        ConfigStartVo configStart = dataConfigService.getConfigStartConfig(curStartId);
        if (ObjectUtil.isNull(configStart)) {
            log.error("未获取到开局配置: {}", curStartId);
            return 0;
        }
        // 根据当前步骤判断下发通知类型
        // 助力提现值的通知(必须新用户)
        Integer drawStartStep = configStart.getGetDrawValue();
        // 助力流程通知
        Integer shareStartStep = configStart.getShareProgressId();

        // 多阶段列表
        List<Integer> startStepList = new ArrayList<>();
        if (MyTool.isTure(drawStartStep)) {
            startStepList.add(drawStartStep);
        }
        if (MyTool.isTure(shareStartStep)) {
            startStepList.add(shareStartStep);
        }

        // 对列表进行从大到小排序
        startStepList.sort(Comparator.reverseOrder());
        //
        for (Integer startStep : startStepList) {
            if (curStepId < startStep) {
                continue;
            }
            // 助力提现值的通知(必须新用户)
            if (startStep.equals(drawStartStep)) {
                if (!isNewUser) {
                    return 0;
                }
                return EServerNoticeTypeDto.DRAW_VALUE_NOTICE;
            }
            // 助力流程通知
            if (startStep.equals(shareStartStep)) {
                return EServerNoticeTypeDto.NEW_INVITE_TO_PROGRESS;
            }
            // ...

        }

        // 默认的
        return EServerNoticeTypeDto.NEW_INVITE;
    }

    /**
     * 更新新邀请个数
     *
     * @param player
     */
    private void addNewsCount(PlayerInfoVo player) {
        UserActivityVo activity = player.getActivity();
        Integer newUserCount = activity.getNewUserCount();
        activity.setNewUserCount(newUserCount + 1);
        player.getMaster().getSaveList().add(CutSaveKey.USER_ACTIVITY_NEWS_COUNT);
    }

    @Override
    public Void removeNoticeType(PlayerInfoVo player, Integer oneNotice) {
        Integer[] list = player.getActivity().getNoticeTypeList();
        List<Integer> noticeList = Lists.newArrayList(list);
        if (!noticeList.contains(oneNotice)) {
            return null;
        }

        noticeList.remove(oneNotice);
        player.getActivity().setNoticeTypeList(noticeList.toArray(new Integer[0]));
        player.getMaster().getSaveList().add(CutSaveKey.USER_ACTIVITY_NOTICE_TYPE_LIST);
        return null;
    }

    @Override
    public void removeAllNoticeType(PlayerInfoVo player) {
        player.getActivity().setNoticeTypeList(new Integer[0]);
        player.getMaster().getSaveList().add(CutSaveKey.USER_ACTIVITY_NOTICE_TYPE_LIST);
    }

    /**
     * @param player
     * @param oneNotice
     * @return
     */
    @Override
    public Void addNoticeType(PlayerInfoVo player, Integer oneNotice) {
        if (!MyTool.isTure(oneNotice)) {
            return null;
        }

        Integer[] list = player.getActivity().getNoticeTypeList();
        ArrayList<Integer> array = Lists.newArrayList(list);
        if (array.contains(oneNotice)) {
            return null;
        }
        array.add(oneNotice);
        list = array.toArray(new Integer[0]);

        player.getActivity().setNoticeTypeList(list);
        player.getMaster().getSaveList().add(CutSaveKey.USER_ACTIVITY_NOTICE_TYPE_LIST);
        return null;
    }

    @Override
    public Integer[] getSendClientNoticeType(PlayerInfoVo player) {
        // 若是处于助力流程, 则不发送助力成功的通知
        Integer curStepId = player.getFlowInfo().getStepId();
        Integer[] curNoticeList = player.getActivity().getNoticeTypeList();

        ConfigProgressVo configProgress = dataConfigService.getConfigProgressConfig(curStepId);
        if (ObjectUtil.isNotNull(configProgress)) {
            Integer type = configProgress.getProgressType();
            if (ObjectUtil.isNotNull(type) && type.equals(ProgressTypeEnum.HELP.getValue())) {
                // 助力流程
                List<Integer> noticeList = Lists.newArrayList(curNoticeList);
                // 移除属于助力的通知
                noticeList.remove(EServerNoticeTypeDto.NEW_INVITE);
                noticeList.remove(EServerNoticeTypeDto.NEW_INVITE_TO_PROGRESS);
                noticeList.remove(EServerNoticeTypeDto.DRAW_VALUE_NOTICE);

                curNoticeList = noticeList.toArray(new Integer[0]);
            }
        }
        return curNoticeList;
    }

    /**
     * 是否含有某个通知
     * @param player
     * @param oneNotice
     */
    @Override
    public boolean isHasNotice(PlayerInfoVo player, Integer oneNotice) {
        Integer[] list = player.getActivity().getNoticeTypeList();
        for (int i = 0; i < list.length; ++i) {
            if (list[i].equals(oneNotice)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 分享邀请成功
     *
     * @param player
     */
    @Override
    public void addShareCount(PlayerInfoVo player, Integer addCount) {
        Integer shareCount = player.getActivity().getShareCount();
        player.getActivity().setShareCount(shareCount + addCount);
        player.getMaster().getSaveList().add(CutSaveKey.USER_ACTIVITY_SHARE_SUCCESS);
    }

    /**
     * 判断用户是否是新用户 （如果是当天注册为新用户）
     *
     * 返回 1 ： 新用户
     * 返回 0 ： 老用户
     */
    public Integer ifNewUser(PlayerInfoVo player) {
        Integer registerTime = player.getBase().getCreateTime();
        Date registerDate = new Date(registerTime * 1000L);
        log.debug("============================>注册日期: {}", registerDate);
        boolean isToday = cn.hutool.core.date.DateUtil.isSameDay(new Date(), registerDate);
        if (!isToday) {
            return CutConstants.USER_TYPE_OLD;
        }

        // 新用户如果已经助力过, 则变成老用户
        boolean hasHelped = inviteSuccessDBService.checkExitByInvitedAccount(player.getBase().getAccount());
        return hasHelped ? CutConstants.USER_TYPE_OLD : CutConstants.USER_TYPE_NEW;
    }

    /**
     * 重置用户的活动, 回到初始状态
     *
     * @param player
     */
    @Override
    public void resetActivity(PlayerInfoVo player) {
        // 活动id, 开局id不变. 清空其它数据

        // 1.清空背包
        userBagService.cleanBag(player);
        // 2.活动信息重置
        this.resetUserActivityData(player);
        // 3.订单重置
        userOrderService.resetAllOrders(player);
        // 4.订单重置
        userCashDetailListService.clearCashDetail(player);
        // 5.流程
        userFlowService.refreshFlowData(player);
        // 6.转盘


        // 刷新缓存
//        userManagerService.refreshPlayerCache(player);
    }

    private void resetUserActivityData(PlayerInfoVo player) {
        UserActivityVo userActivity = player.getActivity();
        Long curTimeLong = MyTool.getCurrentTime();
        userActivity.setBeganTime(curTimeLong.intValue());
        userActivity.setNewUserCount(0);
        userActivity.setShareCount(0);
        userActivity.setNoticeTypeList(new Integer[0]);
        userActivity.setGainPrize(0);
        userActivity.setInvitedCount(0);
        userActivity.setWatchLive(0);
        // 更新数据库
        DBUserActivityInfo dbData = DBUserActivityInfo.builder().build();
        dbData.setWatchLive(0);
        dbData.setGainPrize(0);
        dbData.setActivityId(player.getActivity().getActivityId());
        dbData.setNotice(new Integer[0]);
        dbData.setBeganTime(new Date());
        dbData.setImageUrl("");
        dbData.setWatchLive(0);
        dbData.setShareCount(0);
        dbData.setNewUserCount(0);
        dbData.setUid(player.getBase().getUid());
        dbData.setStatus(0);
        dbData.setActivityStartId(player.getActivity().getStartId());

        userActivityDBService.updateData(dbData);
    }


    @Override
    public int calLeftNeedNewerCount(PlayerInfoVo player, int curCount) {
        // 总需邀请数
        int totalCount = this.getAllNeedNewerCount(player.getActivity().getStartId());
        if (totalCount < 0) {
            log.error("总需邀请数计算错误!");
            return 999999;
        }

        // 剩余邀请数
        int leftInviteCount = totalCount - curCount;
        if (leftInviteCount < 0) {
            leftInviteCount = 0;
        }

        return leftInviteCount;
    }

    @Override
    public int getAllNeedNewerCount(Integer startId) {
        ConfigStartVo configStartVo = dataConfigService.getConfigStartConfig(startId);
        if (ObjectUtil.isNull(configStartVo)) {
            log.error("开局 {} 配置错误!", startId);
            return -1;
        }
        // 总金额
        Integer totalCoin = configStartVo.getGold();
        if (!MyTool.isTure(totalCoin)) {
            log.error("总金额配置错误!");
            return -1;
        }
        ConfigGlobalGlobalVo configGlobalGlobalVo = dataConfigService.getConfigGlobalGlobalConfig();
        if (ObjectUtil.isNull(configGlobalGlobalVo)) {
            log.error("全局配置错误!");
            return -1;
        }
        // 单用户价值
        Integer newersValue = configGlobalGlobalVo.getNewersCoin();
        if (!MyTool.isTure(newersValue)) {
            log.error("用户价值配置错误!");
            return -1;
        }
        // 总邀请数
        int total = totalCoin / newersValue;
        return total;
    }

    @Override
    public boolean isFinishInviteAllNewer(PlayerInfoVo player) {
        // 当前已邀请新用户数
        Integer uid = player.getBase().getUid();
        Integer activityId = player.getActivity().getActivityId();
        int inviteCount = userInviteSuccessDBService.selectInviteNewersCount(uid, activityId);
        int leftNeedNewerCount = userActivityService.calLeftNeedNewerCount(player, inviteCount);
        return leftNeedNewerCount == 0;
    }
}
